import { DecisionTreeNode } from "./DecisionTreeNode";

export abstract class BinaryDecision<T extends IStateArg = IStateArg> extends DecisionTreeNode<T> implements ICondition<T>
{
    type:number=0;
    private trueNode?:DecisionTreeNode;
    private falseNode?:DecisionTreeNode;
    constructor(trueNode?:DecisionTreeNode,falseNode?:DecisionTreeNode)
    {
        super();
        this.trueNode = trueNode;
        this.falseNode = falseNode;
    }
    public abstract testValue(arg:T):boolean;
    public   getBranch(arg:T):DecisionTreeNode|undefined
    {
        if(this.testValue( arg))
        {
            return this.trueNode;
        }
        else
        {
            return this.falseNode;
        }
    }
    public test(arg:T):boolean
    {
        return this.testValue(arg);
    }
    public makeDecision(arg:T): DecisionTreeNode|undefined
    {
        const banch = this.getBranch(arg);
        return  banch;

    }

}

export abstract class  DecisionMapping  <T extends IStateArg = IStateArg> extends DecisionTreeNode<T> implements ICondition<T>
{
    type: number=0;
    constructor( childNodes:Record<string,DecisionTreeNode>)
    {
        super();
        this.childNodes = childNodes;
    }
    protected childNodes:Record<string,DecisionTreeNode>={};

    protected abstract getkey(arg:T):string|undefined;
    public     testValue(arg:T):boolean
    {
        const key = this.getkey(arg);
        if(!key)
        {
            return false;
        }
        const node = this.childNodes[key];
        if(node)
        {
            return true;
        }
        return false;
    }
    public test(arg:T):boolean
    {
        return this.testValue(arg);
    }
    public makeDecision(arg:T): DecisionTreeNode|undefined
    {
        const key = this.getkey( arg);
        if(key)
        {
            return this.childNodes[key];
        }
        return undefined;
    }
}
